/**
 * Copyright 2000 self.com.au
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License. (http://www.apache.org/licenses/LICENSE-2.0)
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed 
 * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for 
 * the specific language governing permissions and limitations under the License.
 *
 * <dhamma-message src="Atisha (11th century Tibetan Buddhist master)">
 * 	The greatest achievement is selflessness. The greatest worth is self-mastery.
 * 	The greatest quality is seeking to serve others. The greatest precept is continual awareness.
 * 	The greatest medicine is the emptiness of everything. The greatest action is not conforming with the worlds ways.
 * 	The greatest magic is transmuting the passions. The greatest generosity is non-attachment.
 * 	The greatest goodness is a peaceful mind. The greatest patience is humility.
 * 	The greatest effort is not concerned with results. The greatest meditation is a mind that lets go.
 * 	The greatest wisdom is seeing through appearances. 
 * </dhamma-message>
 *
 * @author Ashin Wimalajeewa
 */
package self.amigo.elem;

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.util.HashMap;
import java.util.Map;

import org.w3c.dom.DOMException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;

import self.awt.ATextRenderInfoAdapter;
import self.awt.FontUtils;
import self.awt.ITextRenderInfo;
import self.awt.PainterManager;
import self.awt.painter.TextPainter;
import self.gee.IDiagramLayer;
import self.lang.BooleanUtils;
import self.lang.StringUtils;
import self.xml.DomUtils;

public class TextView extends ARectangularLinkable {
	
	/**
	 * If the internal state of this class ever changes in such a way that it can't be defaulted,
	 * then the {@link #serialVersionUID} should be incremented to ensure serialized instances cleanly fail.  
	 */
	private static final long serialVersionUID = 1;
	
	final static public   String TEXTCOLOR_PROP = "textcolor";

  final static public   String FILL_PROP = "Fill";
  final static public   String TEXT_PROP = "text";
  final static public   String FONT_PROP = "font";
  final static public   String SHOWFRAME_PROP = "showFrame";

  final static public String AID_PROP = "aid";

  public TextView() {
    delegate =  new Essential();
    setDelegate( delegate );
  }

  public class Essential extends ARectangularHandledElement {
  	
	/**
	 * If the internal state of this class ever changes in such a way that it can't be defaulted,
	 * then the {@link #serialVersionUID} should be incremented to ensure serialized instances cleanly fail.  
	 */
	private static final long serialVersionUID = 1;
	
    private FillableFeature       fillData = new FillableFeature();
    private ColorFeature          frameColorData = new ColorFeature( AGraphicElement.FRAMECOLOR_PROP );
    private ColorFeature          textColorData = new ColorFeature( TEXTCOLOR_PROP );
    private boolean               showFrame = true;
    protected Font                font = new Font( "Arial", 0, 12 );
    protected String              text = "Text";
    protected String aidLink;

    transient protected PaintContext        context = new PaintContext();
    protected TextPainter         textPainter;

    public void       setLayer( IDiagramLayer layerToDrawOn, boolean add ) {
      super.setLayer( layerToDrawOn, add );
      textPainter = (TextPainter) PainterManager.getPainterForOwner( layer, TextPainter.class );
    }

    public void       paint( Graphics surface ) {
      if ( outlineOnly ) {
        surface.setColor( frameColor );
        surface.drawRect( fig.x, fig.y, fig.width, fig.height );
        return;
      }

      if (fillData.fillColor != null) {
        surface.setColor(fillData.fillColor);
        surface.fillRect( fig.x, fig.y, fig.width, fig.height );
      }
      if ( showFrame ) {
        surface.setColor( frameColorData.color );
        surface.drawRect( fig.x, fig.y, fig.width, fig.height );
      }

      surface.setColor(frameColor);
      boolean paintSymbol = aidLink != null;
      if ( paintSymbol ) {
        surface.setFont( font );
        SymbolPaintManagerUtils.startSymbol( surface, this, aidLink );
      }
      try {
        textPainter.paint( surface, context, outlineOnly );
      } finally {
        if ( paintSymbol )
          SymbolPaintManagerUtils.endSymbol( surface );
      }
    }

    // IEditableElement support
    public void       getProperties( Map store ) {
      store.put( FILL_PROP, fillData.clone() );
      textColorData.getProperties( store );
      frameColorData.getProperties( store );
      store.put( TEXT_PROP, text );
      store.put( FONT_PROP, font );
      store.put( SHOWFRAME_PROP, BooleanUtils.toBoolean(showFrame) );
      store.put( AID_PROP, aidLink );
    }

    public void       setProperties( Map data ) {
      fillData.set( (FillableFeature) data.get(FILL_PROP) );
      textColorData.setProperties( data );
      frameColorData.setProperties( data );
      text = (String) data.get( TEXT_PROP );
      font = (Font) data.get( FONT_PROP );
      showFrame = BooleanUtils.toPrimitive( data.get(SHOWFRAME_PROP) );
      aidLink = (String) data.get( AID_PROP );
      layer.setDirty();
    }

    // IPersistentElement support
    public void readFrom( Node self, HashMap idObjLookUp ) throws DOMException {
      super.readFrom( self, idObjLookUp );
      text = DomUtils.getElementText( self );
      fillData.readFrom( self, idObjLookUp );
      textColorData.readFrom( self, idObjLookUp );
      frameColorData.readFrom( self, idObjLookUp );
      String fontAsString = DomUtils.getElementAttribute( self, FONT_PROP );
      font = Font.decode( fontAsString );
      try {
        showFrame = BooleanUtils.toValue( DomUtils.getElementAttribute(self, SHOWFRAME_PROP) );
      } catch ( Exception err ) {
    	// nothing to do.
      }
      aidLink = DomUtils.getElementAttribute( self, AID_PROP, null );
    }

    public void writeTo( Document doc, Element self, HashMap objIdLookup ) throws DOMException {
      super.writeTo( doc, self, objIdLookup );
      DomUtils.setElementText( self, StringUtils.toEmptyIfNull(text) );
      fillData.writeTo( doc, self, objIdLookup );
      textColorData.writeTo( doc, self, objIdLookup );
      frameColorData.writeTo( doc, self, objIdLookup );
      String fontAsString = FontUtils.encode( font );
      DomUtils.setElementAttribute( self, FONT_PROP, StringUtils.toEmptyIfNull(fontAsString) );
      DomUtils.setElementAttribute( self, SHOWFRAME_PROP, BooleanUtils.toString(showFrame) );
      if ( !StringUtils.isNullOrEmpty(aidLink) )
        DomUtils.setElementAttribute( self, AID_PROP, StringUtils.toEmptyIfNull(aidLink) );
    }

    protected class PaintContext extends ATextRenderInfoAdapter {
      public PaintContext() {
        format = ITextRenderInfo.WRAPPED_FORMAT;
      }

      public String     getText() {
        return text;
      }

      public Rectangle  getBounds() {
        return fig;
      }

      public Font       getFont() {
        return font;
      }

      public Color      getColor() {
        return textColorData.color;
      }
    }
  }
}
